//const DELETE_ICON = 'common/images/close.png'; // 删除按钮
var DELETE_ICON=""

//const DRAG_ICON = 'common/images/scale.png'; // 缩放按钮
var DRAG_ICON=""

const STROKE_COLOR = '#ff0000';
const ROTATE_ENABLED = true;
let isMove = false; // 标识触摸后是否有移动，用来判断是否需要增加操作历史

const DEBUG_MODE = false; // 打开调试后会渲染操作区域边框（无背景时有效）
// @ts-ignore

export const dragGraph = function ({x = 30, y = 30, w, h, typeStr, text, fontSize = 20,bgColor, textColor = '#ff0000', url = null, rotate = 0, sourceId = null, selected = true}, canvas) {
    if (typeStr === 'text') {
        canvas.font = fontSize + 'px sans-serif';
        const textWidth = canvas.measureText(text).width;
        const textHeight = fontSize + 10;
        this.centerX = x + textWidth / 2;
        this.centerY = y + textHeight / 2;
        this.w = textWidth;
        this.h = textHeight;
        console.info('dragGraph-------------------text-------->')
    } else {
        this.centerX = x + w / 2;
        this.centerY = y + h / 2;
        this.w = w;
        this.h = h;
    }

    this.x = x;
    this.y = y;

    // 4个顶点坐标
    this.square = [
        [this.x, this.y],
        [this.x + this.w, this.y],
        [this.x + this.w, this.y + this.h],
        [this.x, this.y + this.h]
    ];
    console.info('dragGraph-------------square---->' + this.square)

    this.fileUrl = url;
    this.text = text;
    this.fontSize = fontSize;
    this.textColor = textColor;
    this.bgColor=bgColor;
    this.ctx = canvas;
    this.rotate = rotate;
    this.typeStr = typeStr;
    this.selected = selected;
    this.sourceId = sourceId;
    this.MIN_WIDTH = 20;
    this.MIN_FONTSIZE = 10;
}

/**
  * 绘制元素
  */
dragGraph.prototype = {
    paint() {
        getApp().data.ctx.clearRect(this.x, this.y, this.width, this.height)
        getApp().data.ctx.save();
        // 由于measureText获取文字宽度依赖于样式，所以如果是文字元素需要先设置样式
        let textWidth = 0;
        let textHeight = 0;
        console.info('paint---------type---->' + this.typeStr);
        if (this.typeStr === 'text') {
            this.ctx.font = this.fontSize + 'px sans-serif';
            this.ctx.textBaseline = 'middle';
            this.ctx.textAlign = 'center'
            this.ctx.fillStyle =this.textColor
            this.ctx.fill()
            this.ctx.save()
            textWidth = this.ctx.measureText(this.text).width;
            textHeight = this.fontSize + 10;
            // 字体区域中心点不变，左上角位移
            this.x = this.centerX - textWidth / 2;
            this.y = this.centerY - textHeight / 2;
        }

        // 旋转元素
        this.ctx.translate(this.centerX, this.centerY);

        this.ctx.rotate(this.rotate * Math.PI / 180);

        this.ctx.translate(-this.centerX, -this.centerY);


        // 渲染元素
        if (this.typeStr === 'text') {

            this.ctx.fillText(this.text,this.centerX, this.centerY);

            //        this.ctx.restore();
        } else if (this.typeStr === 'image') {

            this.ctxDrawImage(this.fileUrl, this.x, this.y, this.w, this.h)
        }
        // 如果是选中状态，绘制选择虚线框，和缩放图标、删除图标
        if (this.selected) {
            this.ctx.setLineDash([2, 5]);
            this.ctx.lineWidth = 2;
            this.ctx.strokeStyle = STROKE_COLOR;
            this.ctx.lineDashOffset = 6;
            if (this.typeStr === 'text') {
                this.ctx.strokeRect(this.x, this.y, textWidth, textHeight);
                this.ctxDrawImage(DELETE_ICON, this.x - 15, this.y - 15, 30, 30);
                this.ctxDrawImage(DRAG_ICON, this.x + textWidth - 15, this.y + textHeight - 15, 30, 30);
            } else {
                this.ctx.strokeRect(this.y, this.w, this.h);
                this.ctxDrawImage(DELETE_ICON, this.x - 15, this.y - 15, 30, 30);
                this.ctxDrawImage(DRAG_ICON, this.x + this.w - 15, this.y + this.h - 15, 30, 30);
            }
        }
        getApp().data.ctx.restore();
    },


    ctxDrawImage(url, x, y, x1, y1) {
        var img = new Image();
        img.src = url;
        this.ctx.drawImage(img, x, y, x1, y1);

    },


    /**
   * 给矩形描边
   *
   */
    drawBorder() {
        let p = this.square;
        this.ctx.save();
        this.ctx.beginPath();
        this.ctx.strokeStyle = 'orange';
        this.draw_line(p[0], p[1]);
        this.draw_line(p[1], p[2]);
        this.draw_line(p[2], p[3]);
        this.draw_line(p[3], p[0]);
        this.ctx.restore();
    },


    /**
     * 画一条线
     * @param a
     * @param b
     * @private
     */
    draw_line(a, b) {
        console.info('paint---------start()--_draw_line-->');
        this.ctx.moveTo(a[0], a[1]);
        this.ctx.lineTo(b[0], b[1]);
        this.ctx.stroke();
    },


    /**
     * 判断点击的坐标落在哪个区域
     * @param {*} x 点击的坐标
     * @param {*} y 点击的坐标
     */
    isInGraph(x, y) {
        console.info('paint---------start()--isInGraph-->');
        // 删除区域左上角的坐标和区域的高度宽度
        const delW = 30;
        const delH = 30;

        // 旋转后的删除区域坐标
        const transformedDelCenter = this.rotatePoint(this.x, this.y, this.centerX, this.centerY, this.rotate);
        const transformDelX = transformedDelCenter[0] - delW / 2;
        const transformDelY = transformedDelCenter[1] - delH / 2;

        // 变换区域左上角的坐标和区域的高度宽度
        const scaleW = 30;
        const scaleH = 30;
        const transformedScaleCenter = this.rotatePoint(this.x + this.w, this.y + this.h, this.centerX, this.centerY, this.rotate);

        // 旋转后的变换区域坐标
        const transformScaleX = transformedScaleCenter[0] - scaleW / 2;
        const transformScaleY = transformedScaleCenter[1] - scaleH / 2;

        // 调试使用，标识可操作区域
        if (DEBUG_MODE) {
            // 标识删除按钮区域
            this.ctx.lineWidth = 1;
            this.ctx.strokeStyle = '#ff0000'
            this.ctx.strokeRect(transformDelX, transformDelY, delW, delH);
            // 标识旋转/缩放按钮区域
            this.ctx.lineWidth = 1;
            this.ctx.strokeStyle = 'black'
            this.ctx.strokeRect(transformScaleX, transformScaleY, scaleW, scaleH);
            // 标识移动区域
            this.drawBorder();
        }

        if (x - transformScaleX >= 0 && y - transformScaleY >= 0 &&
        transformScaleX + scaleW - x >= 0 && transformScaleY + scaleH - y >= 0) {
            // 缩放区域
            return 'transform';
        } else if (x - transformDelX >= 0 && y - transformDelY >= 0 &&
        transformDelX + delW - x >= 0 && transformDelY + delH - y >= 0) {
            // 删除区域
            return 'del';
        } else if (this.insidePolygon(this.square, [x, y])) {
            return 'move';
        }
        // 不在选择区域里面
        return false;
    },

    /**
     *  判断一个点是否在多边形内部
     *  @param points 多边形坐标集合
     *  @param testPoint 测试点坐标
     *  返回true为真，false为假
     *  */
    insidePolygon(points, testPoint) {
        console.log('paint---------start()--insidePolygon-->');
        let x = testPoint[0], y = testPoint[1];
        let inside = false;
        for (let i = 0, j = points.length - 1; i < points.length; j = i++) {
            let xi = points[i][0], yi = points[i][1];
            let xj = points[j][0], yj = points[j][1];

            let intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
            if (intersect) inside = !inside;
        }
        return inside;
    },

    /**
     * 计算旋转后矩形四个顶点的坐标（相对于画布）
     * @private
     */
    rotateSquare() {
        this.square = [
            this.rotatePoint(this.x, this.y, this.centerX, this.centerY, this.rotate),
            this.rotatePoint(this.x + this.w, this.y, this.centerX, this.centerY, this.rotate),
            this.rotatePoint(this.x + this.w, this.y + this.h, this.centerX, this.centerY, this.rotate),
            this.rotatePoint(this.x, this.y + this.h, this.centerX, this.centerY, this.rotate),
        ];
    },
    /**
     * 计算旋转后的新坐标（相对于画布）
     * @param x
     * @param y
     * @param centerX
     * @param centerY
     * @param degrees
     * @returns {*[]}
     * @private
     */
    rotatePoint(x, y, centerX, centerY, degrees) {
        let newX = (x - centerX) * Math.cos(degrees * Math.PI / 180) - (y - centerY) * Math.sin(degrees * Math.PI / 180) + centerX;
        let newY = (x - centerX) * Math.sin(degrees * Math.PI / 180) + (y - centerY) * Math.cos(degrees * Math.PI / 180) + centerY;
        return [newX, newY];
    },


    /**
     *
     * @param {*} px 手指按下去的坐标
     * @param {*} py 手指按下去的坐标
     * @param {*} x 手指移动到的坐标
     * @param {*} y 手指移动到的坐标
     * @param {*} currentGraph 当前图层的信息
     */

    transform(px, py, x, y, currentGraph) {
        // 获取选择区域的宽度高度
        if (this.typeStr === 'text') {
            this.ctx.font = this.fontSize + 'px sans-serif';
            console.info('-----paint----------------text---------------->' + this.text)
            const textWidth = this.ctx.measureText(this.text).width;
            const textHeight = this.fontSize + 10;
            this.w = textWidth;
            this.h = textHeight;
            // 字体区域中心点不变，左上角位移
            this.x = this.centerX - textWidth / 2;
            this.y = this.centerY - textHeight / 2;
        } else {
            this.centerX = this.x + this.w / 2;
            this.centerY = this.y + this.h / 2;
        }

        const diffXBefore = px - this.centerX;
        const diffYBefore = py - this.centerY;
        const diffXAfter = x - this.centerX;
        const diffYAfter = y - this.centerY;

        const angleBefore = Math.atan2(diffYBefore, diffXBefore) / Math.PI * 180;
        const angleAfter = Math.atan2(diffYAfter, diffXAfter) / Math.PI * 180;

        // 旋转的角度
        if (ROTATE_ENABLED) {
            this.rotate = currentGraph.rotate + angleAfter - angleBefore;
        }

        const lineA = Math.sqrt(Math.pow((this.centerX - px), 2) + Math.pow((this.centerY - py), 2));
        const lineB = Math.sqrt(Math.pow((this.centerX - x), 2) + Math.pow((this.centerY - y), 2));
        if (this.typeStr === 'image') {
            let resize_rito = lineB / lineA;
            let new_w = currentGraph.w * resize_rito;
            let new_h = currentGraph.h * resize_rito;

            if (currentGraph.w < currentGraph.h && new_w < this.MIN_WIDTH) {
                new_w = this.MIN_WIDTH;
                new_h = this.MIN_WIDTH * currentGraph.h / currentGraph.w;
            } else if (currentGraph.h < currentGraph.w && new_h < this.MIN_WIDTH) {
                new_h = this.MIN_WIDTH;
                new_w = this.MIN_WIDTH * currentGraph.w / currentGraph.h;
            }

            this.w = new_w;
            this.h = new_h;
            this.x = currentGraph.x - (new_w - currentGraph.w) / 2;
            this.y = currentGraph.y - (new_h - currentGraph.h) / 2;

        } else if (this.typeStr === 'text') {
            const fontSize = currentGraph.fontSize * ((lineB - lineA) / lineA + 1);
            this.fontSize = fontSize <= this.MIN_FONTSIZE ? this.MIN_FONTSIZE : fontSize;

            // 旋转位移后重新计算坐标
            this.ctx.font = this.fontSize + 'px sans-serif';
            const textWidth = this.ctx.measureText(this.text).width;
            const textHeight = this.fontSize + 10;
            this.w = textWidth;
            this.h = textHeight;
            // 字体区域中心点不变，左上角位移
            this.x = this.centerX - textWidth / 2;
            this.y = this.centerY - textHeight / 2;
        }
    }


}

export default {
    props: {
        ctx: {
            default: {},
        },
        graph: {
            default: {},
        },
        bgColor: {
            default: '',
        },
        bgImage: {
            default: '',
        },
        bgSourceId: {
            default: '',
        },
        width: {
            default: 750,
        },
        height: {
            default: 750,
        },
        enableUndo: {
            default: false,
        },
        operation: {
            default: {},
        },
        operationbg:{
            default:[],
        }
    },
    /**
     * 组件的初始数据
     */
    data: {
        history: [],
    },
    onInit() {
         DELETE_ICON=this.operationbg[0];
         console.debug("----------{"+this.operationbg[0]+"}")
         DRAG_ICON=this.operationbg[1]
         console.debug("----------{"+this.operationbg[1]+"}")
        this.attached()
        this.$watch('graph', 'onGraphChange');
        this.$watch('operation', 'onOperationChange')
    },
    attached() {
        if (typeof this.drawArr === 'undefined') {
            this.drawArr = [];

        }

    },

    initBg() {
        this.bgColor = '';
        this.bgSourceId = '';
        this.bgImage = '';
    },


    initHistory() {
        this.history = [];
    },


    recordHistory() {
        if (!this.enableUndo) {
            return;
        }
        this.exportJson()
            .then((imgArr) => {
                this.history.push(JSON.stringify(imgArr));
            })
            .catch((e) => {
                console.error(e);
            });
    },

    onGraphChange(newV, ) {
        // @ts-ignore

        this.ctx = getApp().data.ctx
        console.info('-----onGraphChange-------->' + this.ctx)

        if (JSON.stringify(newV) === '{}') return;


        if (this.bgImage === '' && this.bgColor === '') {
            this.changeBgColor('#ffffff')
        }


        this.drawArr.push(new dragGraph(Object.assign({
            x: 30,
            y: 30,
            // @ts-ignore
        }, newV), getApp().data.ctx));

        console.info('drawArr------>' + JSON.stringify(this.drawArr));
        this.draw();
        // 参数有变化时记录历史
        this.recordHistory();


    },
    initByArr(newArr) {
        //        this.drawArr.forEach(item => {
        //            item.clearCanvas()
        //        });

        this.drawArr = []; // 重置绘画元素
        this.initBg(); // 重置绘画背景
        // 循环插入 drawArr
        newArr.forEach((item, index) => {
            switch (item.typeStr) {
                case 'bgColor':
                    this.bgImage = '';
                    this.bgSourceId = '';
                    this.bgColor = item.bgColor;
                    break;
                case 'bgImage':
                    this.bgColor = '';
                    this.bgImage = item.url;
                    if (item.sourceId) {
                        this.bgSourceId = item.sourceId;
                    }
                    break;
                case 'image':
                case 'text':
                    if (index === newArr.length - 1) {
                        item.selected = true;
                    } else {
                        item.selected = false;
                    }
                    this.drawArr.push(new dragGraph(item, this.ctx));
                    break;
            }

        });
        this.draw();
    },
    draw() {

        console.info("bgImage------------->" + this.bgImage)
        // @ts-ignore
        if (this.bgImage !== "") {

            this.ctxDrawImage(this.bgImage, 0, 0, this.width, this.height)
        }
        // @ts-ignore
        if (this.bgColor !== '') {
            console.info('------------------->'+this.bgColor)
            getApp().data.ctx.save()
            this.ctx.fillStyle = this.bgColor;
            getApp().data.ctx.fillRect(0, 0, this.width, this.height);


            this.ctx.stroke();
            console.info('---------draw-----end---->')
        }

        console.info("drawArr------------->" + JSON.stringify(this.drawArr))

        this.drawArr.forEach((item) => {
            item.paint();

        });
        //


        return new Promise((resolve) => {
            this.ctx.draw(false, () => {
                resolve();
            });

        });


    },
    start(e) {
        console.info(`on touch start, point is--------------->: ${e.touches[0].globalX}`);
        isMove = false; // 重置移动标识
        let x = e.touches[0].globalX
        let y = e.touches[0].globalY
        console.info(`on touch start, point is--------------->: x===` + x + '-------y====' + y);
        this.tempGraphArr = [];
        let lastDelIndex = null; // 记录最后一个需要删除的索引
        this.drawArr && this.drawArr.forEach((item, index) => {

            const action = item.isInGraph(x, y);

            if (action) {
                item.action = action;
                this.tempGraphArr.push(item);

                // 保存点击时的坐标
                this.currentTouch = {
                    x, y
                };
                if (action === 'del') {
                    lastDelIndex = index; // 标记需要删除的元素
                }
            } else {
                item.action = false;
                item.selected = false;
            }
        });

        console.info('------------------tempGraphArr----json------->>>>>>' + JSON.stringify(this.tempGraphArr))
        // 保存点击时元素的信息
        if (this.tempGraphArr.length > 0) {

            for (let i = 0; i < this.tempGraphArr.length; i++) {
                let lastIndex = this.tempGraphArr.length - 1;
                // 对最后一个元素做操作
                if (i === lastIndex) {
                    // 未选中的元素，不执行删除和缩放操作
                    if (lastDelIndex !== null && this.tempGraphArr[i].selected) {

                        console.info('------------------tempGraphArr----------->>>>>>' + '未选中的元素，不执行删除和缩放操作')
                        if (this.drawArr[lastDelIndex].action === 'del') {
                            this.drawArr.splice(lastDelIndex, 1);
                            this.ctx.clearRect(0, 0, this.width, this.height);
                        }
                        console.info('------------------tempGraphArr----------->>>>>>' + '未选中的元素，不执行删除和缩放操作====end')
                    } else {
                        this.tempGraphArr[lastIndex].selected = true;
                        this.currentGraph = Object.assign({}, this.tempGraphArr[lastIndex]);
                    }
                } else {
                    // 不是最后一个元素，不需要选中，也不记录状态
                    this.tempGraphArr[i].action = false;
                    this.tempGraphArr[i].selected = false;
                }
            }
        }
        this.draw();
    },
    move(e) {

        let x = e.touches[0].globalX
        let y = e.touches[0].globalY
        console.info('----------------------move--start------->')

        if (this.tempGraphArr && this.tempGraphArr.length > 0) {
            isMove = true; // 有选中元素，并且有移动时，设置移动标识
            const currentGraph = this.tempGraphArr[this.tempGraphArr.length - 1];
            //            currentGraph.clearCanvas()
            if (currentGraph.action === 'move') {
                console.info('----------------------move--------->')
                currentGraph.centerX = this.currentGraph.centerX + (x - this.currentTouch.x);
                currentGraph.centerY = this.currentGraph.centerY + (y - this.currentTouch.y);
                // 使用中心点坐标计算位移，不使用 x,y 坐标，因为会受旋转影响。
                if (currentGraph.typeStr !== 'text') {
                    currentGraph.x = currentGraph.centerX - this.currentGraph.w / 2;
                    currentGraph.y = currentGraph.centerY - this.currentGraph.h / 2;
                }
            } else if (currentGraph.action === 'transform') {
                currentGraph.transform(this.currentTouch.x, this.currentTouch.y, x, y, this.currentGraph);

            }

            // 更新4个坐标点（相对于画布的坐标系）
            //            currentGraph._rotateSquare();
            currentGraph.rotateSquare();

            this.draw();
        }
    },
    end() {
        this.tempGraphArr = [];
        if (isMove) {
            isMove = false; // 重置移动标识
            // 用户操作结束时记录历史
            this.recordHistory();
        }
    },

    ctxDrawImage(url, x, y, x1, y1) {
        var img = new Image();
        img.src = url;
        getApp().data.ctx.drawImage(img, x, y, x1, y1);


    },
    clearCanvas() {
        console.info('-------------clearCanvas-------------------->' + this.ctx)

        this.draw();
        this.drawArr = [];
        this.initBg(); // 重置绘画背景
        this.initHistory(); // 清空历史记录
        this.ctx.clearRect(0, 0, this.width, this.height);
    },
    onOperationChange() {

        this.ctx = getApp().data.ctx;

        console.info('--------------onOperationChange------>' + this.operation)
        if (this.operation.typeStr === 'exportImage') {
            this.exportImage()
        } else if (this.operation.typeStr === 'changeBgColor') {
            this.changeBgColor(this.operation.bgColor);
        } else if (this.operation.typeStr === 'changeBgImage') {
            this.changeBgImage(this.operation.bgImage);
        } else if (this.operation.typeStr === 'changeTextColor') {

            this.changColor(this.operation.textColor);

        } else if (this.operation.typeStr === 'exportJSON') {

            this.exportJson().then((imgArr) => {
                this.$emit('exportJsonResult', JSON.stringify(imgArr))
            })
                .catch((e) => {
                    console.error(e);
                    this.$emit('change', e);
                });

        } else if (this.operation.typeStr === 'importJson') {
            this.initByArr(this.operation.tempTheme);
            if (this.bgImage === '' && this.bgColor === '') {
                this.changeBgColor('#ffffff')
            }

        } else if (this.operation.typeStr === 'clearCanvas') {
            this.clearCanvas();
        } else if (this.operation.typeStr === 'undo') {
            this.undo();
        }


    },
    undo() {
        if (!this.enableUndo) {
            console.log('undo---------->', `后退功能未启用，请设置enableUndo="{{true}}"`);
            return;
        }
        if (this.history.length > 1) {
              console.info('------------history-------->'+this.history.length)
            this.history.pop();
            let newConfigObj = this.history[this.history.length - 1];
            this.initByArr(JSON.parse(newConfigObj));
        } else {
            console.log('undo---------->', '已是第一步，不能回退');
        }
    },
    exportJson() {
        return new Promise((resolve, ) => {
            let exportArr = this.drawArr.map((item) => {
                item.selected = false;
                switch (item.typeStr) {
                    case 'image':
                        return {
                            typeStr: 'image',
                            url: item.fileUrl,
                            y: item.y,
                            x: item.x,
                            w: item.w,
                            h: item.h,
                            rotate: item.rotate,
                            sourceId: item.sourceId,
                        }
                    case 'text':
                        return {
                            typeStr: 'text',
                            text: item.text,
                            textColor: item.textColor===''?"#ff0000":item.textColor,
                            fontSize: item.fontSize,
                            y: item.y,
                            x: item.x,
                            w: item.w,
                            h: item.h,
                            rotate: item.rotate,
                        }
                }
            })
            if (this.bgImage) {
                let tmp_img_config = {
                    typeStr: 'bgImage',
                    url: this.bgImage,
                };
                if (this.bgSourceId) {
                    tmp_img_config['sourceId'] = this.bgSourceId;
                }
                exportArr.unshift(tmp_img_config);
            } else if (this.bgColor) {
                exportArr.unshift({
                    typeStr: 'bgColor',
                    bgColor: this.bgColor
                });
            }

            resolve(exportArr);
        })
    },
    changeBgColor(bgColor) {
        this.bgImage = '';
        this.bgColor = bgColor;
        this.draw();
        // 改变背景颜色时记录历史
        this.recordHistory();
    },
    changeBgImage(newBgImg) {

        this.bgColor = '';
        if (typeof newBgImg == 'string') {
            this.bgSourceId = '';
            this.bgImage = newBgImg;
        } else {
            this.bgSourceId = newBgImg.sourceId;
            this.bgImage = newBgImg.url;
        }
        this.draw();
//        // 改变背景图片时记录历史
        this.recordHistory();
    },
    changColor(textColor) {
        console.info('-----------------------changColor------ this.drawArr----->' + JSON.stringify(this.drawArr))

        const selected = this.drawArr.filter((item) => item.selected);
        if (selected.length > 0) {
            console.info('---------------changColor--------' + textColor)
            selected[0].textColor = textColor;
        }
        this.draw();
        // 改变文字颜色时记录历史
        this.recordHistory();
    },
    /**
     *生成裁剪图片
     */
    exportImage() {
        if (this.ctx == null) {
            // @ts-ignore
            this.ctx = getApp().data.ctx
        }

        var imageData = this.ctx.getImageData(0, 0, this.width, this.height);

        this.$emit('imageData', imageData);


    }
}